﻿#coding=utf-8
#Boa:FramePanel:PanelOrderSale

import wx
import wx.grid
import wx.calendar

import DlgCustomerChoice
import DlgSelectPro
import DlgPayment,DlgEditPro

import dbmngr

from product import *
from config import *
from DlgProGX import *
from ctrlAider import *
from MyListCtrl import *

import  wx.lib.printout as  printout
from MyPrinter import *

import kit
import datetime

[wxID_PANELORDERSALE, wxID_PANELORDERSALEBTNCANCEL, 
 wxID_PANELORDERSALEBTNDELIVERYPLAN, wxID_PANELORDERSALEBTNDRAFT, 
 wxID_PANELORDERSALEBTNHISTORY, wxID_PANELORDERSALEBTNPAYMENT, 
 wxID_PANELORDERSALEBTNPRINT, wxID_PANELORDERSALEBTNSAVE, 
 wxID_PANELORDERSALEBTNSELSTATE, wxID_PANELORDERSALEBTNSHOWCUSTOMER, 
 wxID_PANELORDERSALECHECKBOXDEBT, wxID_PANELORDERSALECOMBOBUYER, 
 wxID_PANELORDERSALECOMBODELIVERY, wxID_PANELORDERSALECOMBOSTAFF, 
 wxID_PANELORDERSALEDATESO, wxID_PANELORDERSALEGRID, 
 wxID_PANELORDERSALESTATICBOX1, wxID_PANELORDERSALESTATICTEXT2, 
 wxID_PANELORDERSALESTATICTEXT3, wxID_PANELORDERSALESTATICTEXT4, 
 wxID_PANELORDERSALESTATICTEXT_MEMO, wxID_PANELORDERSALESTATICTEXT_SHISHOU, 
 wxID_PANELORDERSALESTATICTEXT_STAFF, wxID_PANELORDERSALESTATICTEXT_YINGSHOU, 
 wxID_PANELORDERSALESTATICTEXT_YOUHUI, wxID_PANELORDERSALETBILLID, 
 wxID_PANELORDERSALETBILLNO, wxID_PANELORDERSALETBUYER, 
 wxID_PANELORDERSALETCCUSTOMER, wxID_PANELORDERSALETCDELIVERYPLAN, 
 wxID_PANELORDERSALETCMEMO, wxID_PANELORDERSALETCPAID, 
 wxID_PANELORDERSALETCSHISHOU, wxID_PANELORDERSALETCSTATE, 
 wxID_PANELORDERSALETCTOTAL, wxID_PANELORDERSALETCUNPAID, 
 wxID_PANELORDERSALETCYINGSHOU, wxID_PANELORDERSALETCYOUHUI, 
 wxID_PANELORDERSALETDATE, wxID_PANELORDERSALETDELIVERY, 
 wxID_PANELORDERSALETKEYWORD, wxID_PANELORDERSALETPEER, 
 wxID_PANELORDERSALETSTATE, wxID_PANELORDERSALETTITLE, 
] = [wx.NewId() for _init_ctrls in range(44)]

class PanelOrderSale(wx.Panel):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Panel.__init__(self, id=wxID_PANELORDERSALE, name=u'PanelOrderSale',
              parent=prnt, pos=wx.Point(1, 27), size=wx.Size(1209, 658),
              style=wx.TAB_TRAVERSAL)
        self.SetClientSize(wx.Size(1201, 624))
        self.SetFont(wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, False,
              u'\u6977\u4f53_GB2312'))
        self.SetBackgroundColour(wx.Colour(183, 209, 173))

        self.tTitle = wx.StaticText(id=wxID_PANELORDERSALETTITLE,
              label=u'\u5546\u54c1\u9500\u552e', name=u'tTitle', parent=self,
              pos=wx.Point(240, 32), size=wx.Size(84, 20), style=0)
        self.tTitle.SetFont(wx.Font(15, wx.SWISS, wx.NORMAL, wx.BOLD, False,
              u'\u6977\u4f53_GB2312'))

        self.tBillId = wx.StaticText(id=wxID_PANELORDERSALETBILLID,
              label=u'XS-20150101-00001', name=u'tBillId', parent=self,
              pos=wx.Point(472, 16), size=wx.Size(162, 16), style=0)
        self.tBillId.SetForegroundColour(wx.Colour(0, 0, 0))
        self.tBillId.Show(False)

        self.tBillNo = wx.StaticText(id=wxID_PANELORDERSALETBILLNO,
              label=u'\u5355\u53f7\uff1a', name=u'tBillNo', parent=self,
              pos=wx.Point(408, 16), size=wx.Size(64, 16), style=0)
        self.tBillNo.SetForegroundColour(wx.Colour(0, 0, 0))
        self.tBillNo.Show(False)

        self.tPeer = wx.StaticText(id=wxID_PANELORDERSALETPEER,
              label=u'\u5ba2\u6237\uff1a', name=u'tPeer', parent=self,
              pos=wx.Point(72, 98), size=wx.Size(64, 16), style=0)

        self.TCCustomer = wx.TextCtrl(id=wxID_PANELORDERSALETCCUSTOMER,
              name=u'TCCustomer', parent=self, pos=wx.Point(136, 88),
              size=wx.Size(184, 26), style=0, value=u'')
        self.TCCustomer.SetToolTipString(u'TCCustomer')

        self.btnShowCustomer = wx.Button(id=wxID_PANELORDERSALEBTNSHOWCUSTOMER,
              label=u'+', name=u'btnShowCustomer', parent=self,
              pos=wx.Point(328, 88), size=wx.Size(32, 26), style=0)
        self.btnShowCustomer.Bind(wx.EVT_BUTTON, self.OnBtnShowCustomerButton,
              id=wxID_PANELORDERSALEBTNSHOWCUSTOMER)

        self.staticBox1 = wx.StaticBox(id=wxID_PANELORDERSALESTATICBOX1,
              label=u'', name='staticBox1', parent=self, pos=wx.Point(64, 72),
              size=wx.Size(552, 96), style=0)
        self.staticBox1.SetBackgroundColour(wx.Colour(200, 208, 253))

        self.dateSO = wx.DatePickerCtrl(id=wxID_PANELORDERSALEDATESO,
              name=u'dateSO', parent=self, pos=wx.Point(472, 48),
              size=wx.Size(136, 22), style=wx.DP_DROPDOWN | wx.DP_SHOWCENTURY)
        self.dateSO.SetLabel(u'2013-11-27')
        self.dateSO.SetValue(wx.DateTimeFromDMY(27, 10, 2013, 0, 0, 0))
        self.dateSO.SetWindowVariant(wx.WINDOW_VARIANT_NORMAL)
        self.dateSO.Bind(wx.EVT_DATE_CHANGED, self.OnDateSODateChanged,
              id=wxID_PANELORDERSALEDATESO)

        self.tDate = wx.StaticText(id=wxID_PANELORDERSALETDATE,
              label=u'\u65e5\u671f\uff1a', name=u'tDate', parent=self,
              pos=wx.Point(408, 54), size=wx.Size(56, 16), style=0)

        self.comboDelivery = wx.ComboBox(choices=[],
              id=wxID_PANELORDERSALECOMBODELIVERY, name=u'comboDelivery',
              parent=self, pos=wx.Point(136, 136), size=wx.Size(230, 24),
              style=0, value=u'')
        self.comboDelivery.SetHelpText(u'')
        self.comboDelivery.SetLabel(u'')
        self.comboDelivery.SetStringSelection(u'')
        self.comboDelivery.SetToolTipString(u'')

        self.tDelivery = wx.StaticText(id=wxID_PANELORDERSALETDELIVERY,
              label=u'\u9001\u8d27\uff1a', name=u'tDelivery', parent=self,
              pos=wx.Point(68, 144), size=wx.Size(52, 16), style=0)

        self.grid = wx.grid.Grid(id=wxID_PANELORDERSALEGRID, name=u'grid',
              parent=self, pos=wx.Point(64, 176), size=wx.Size(652, 256),
              style=wx.SUNKEN_BORDER)
        self.grid.SetHelpText(u'')
        self.grid.SetLabel(u'gridSOProList')
        self.grid.SetToolTipString(u'gridSOProList')
        self.grid.SetWindowVariant(wx.WINDOW_VARIANT_LARGE)
        self.grid.SetColLabelSize(32)
        self.grid.SetRowLabelSize(20)
        self.grid.SetColMinimalAcceptableWidth(0)
        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE,
              self.OnGridSOProListGridCellChange)
        self.grid.Bind(wx.grid.EVT_GRID_SELECT_CELL,
              self.OnGridSOProListGridSelectCell)
        self.grid.Bind(wx.grid.EVT_GRID_CELL_RIGHT_CLICK,
              self.OnGridSOProListGridCellRightClick)

        self.staticText_YingShou = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT_YINGSHOU,
              label=u'\u5e94\u6536\u91d1\u989d\uff1a',
              name=u'staticText_YingShou', parent=self, pos=wx.Point(72, 440),
              size=wx.Size(88, 16), style=0)

        self.tcYingShou = wx.TextCtrl(id=wxID_PANELORDERSALETCYINGSHOU,
              name=u'tcYingShou', parent=self, pos=wx.Point(160, 440),
              size=wx.Size(80, 22), style=0, value=u'0.0')
        self.tcYingShou.SetEditable(False)
        self.tcYingShou.Enable(False)

        self.staticText_shishou = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT_SHISHOU,
              label=u'\u5b9e\u6536\u91d1\u989d\uff1a',
              name=u'staticText_shishou', parent=self, pos=wx.Point(264, 440),
              size=wx.Size(88, 16), style=0)

        self.tcShiShou = wx.TextCtrl(id=wxID_PANELORDERSALETCSHISHOU,
              name=u'tcShiShou', parent=self, pos=wx.Point(352, 440),
              size=wx.Size(80, 22), style=0, value=u'0.0')
        self.tcShiShou.SetEditable(False)
        self.tcShiShou.Enable(False)

        self.staticText_YouHui = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT_YOUHUI,
              label=u'\u4f18\u60e0\u91d1\u989d\uff1a',
              name=u'staticText_YouHui', parent=self, pos=wx.Point(448, 440),
              size=wx.Size(88, 16), style=0)

        self.tcYouHui = wx.TextCtrl(id=wxID_PANELORDERSALETCYOUHUI,
              name=u'tcYouHui', parent=self, pos=wx.Point(536, 440),
              size=wx.Size(80, 22), style=0, value=u'0.0')
        self.tcYouHui.SetEditable(True)
        self.tcYouHui.Enable(True)

        self.btnSave = wx.Button(id=wxID_PANELORDERSALEBTNSAVE,
              label=u'\u6b63\u5f0f\u4e0b\u5355', name=u'btnSave', parent=self,
              pos=wx.Point(432, 544), size=wx.Size(93, 26), style=0)
        self.btnSave.Bind(wx.EVT_BUTTON, self.OnBtnSaveButton,
              id=wxID_PANELORDERSALEBTNSAVE)

        self.btnPayment = wx.Button(id=wxID_PANELORDERSALEBTNPAYMENT,
              label=u'\u6536\u6b3e\u8bbe\u7f6e', name=u'btnPayment',
              parent=self, pos=wx.Point(336, 544), size=wx.Size(93, 26),
              style=0)
        self.btnPayment.SetAutoLayout(False)
        self.btnPayment.Show(True)
        self.btnPayment.Bind(wx.EVT_BUTTON, self.OnBtnPaymentButton,
              id=wxID_PANELORDERSALEBTNPAYMENT)

        self.staticText_staff = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT_STAFF,
              label=u'\u7ecf\u624b\u4eba\uff1a', name=u'staticText_staff',
              parent=self, pos=wx.Point(72, 472), size=wx.Size(72, 16),
              style=0)

        self.comboStaff = wx.ComboBox(choices=[],
              id=wxID_PANELORDERSALECOMBOSTAFF, name=u'comboStaff', parent=self,
              pos=wx.Point(160, 472), size=wx.Size(146, 24),
              style=wx.CB_READONLY, value=u'')
        self.comboStaff.SetLabel(u'')

        self.staticText_memo = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT_MEMO,
              label=u'\u5907\u6ce8\uff1a', name=u'staticText_memo', parent=self,
              pos=wx.Point(72, 504), size=wx.Size(72, 16), style=0)

        self.tcMemo = wx.TextCtrl(id=wxID_PANELORDERSALETCMEMO, name=u'tcMemo',
              parent=self, pos=wx.Point(160, 504), size=wx.Size(552, 24),
              style=0, value=u'')

        self.btnPrint = wx.Button(id=wxID_PANELORDERSALEBTNPRINT,
              label=u'\u6253\u5370\u5355\u636e', name=u'btnPrint', parent=self,
              pos=wx.Point(528, 544), size=wx.Size(93, 26), style=0)
        self.btnPrint.Bind(wx.EVT_BUTTON, self.OnBtnPrintButton,
              id=wxID_PANELORDERSALEBTNPRINT)

        self.btnCancel = wx.Button(id=wxID_PANELORDERSALEBTNCANCEL,
              label=u'\u9000\u51fa', name=u'btnCancel', parent=self,
              pos=wx.Point(624, 544), size=wx.Size(93, 26), style=0)
        self.btnCancel.Bind(wx.EVT_BUTTON, self.OnBtnCancelButton,
              id=wxID_PANELORDERSALEBTNCANCEL)

        self.btnHistory = wx.Button(id=wxID_PANELORDERSALEBTNHISTORY,
              label=u'\u5f80\u6765\u5355\u636e', name=u'btnHistory',
              parent=self, pos=wx.Point(736, 40), size=wx.Size(80, 26),
              style=0)
        self.btnHistory.Bind(wx.EVT_BUTTON, self.OnBtnHistoryButton,
              id=wxID_PANELORDERSALEBTNHISTORY)

        self.staticText2 = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT2,
              label=u'\u5e94\u6536\u91d1\u989d\uff1a', name='staticText2',
              parent=self, pos=wx.Point(736, 88), size=wx.Size(85, 16),
              style=0)

        self.TCTotal = wx.TextCtrl(id=wxID_PANELORDERSALETCTOTAL,
              name=u'TCTotal', parent=self, pos=wx.Point(824, 80),
              size=wx.Size(88, 24), style=0, value=u'0.0')
        self.TCTotal.SetEditable(False)
        self.TCTotal.SetInsertionPoint(0)
        self.TCTotal.Enable(True)

        self.TCPaid = wx.TextCtrl(id=wxID_PANELORDERSALETCPAID, name=u'TCPaid',
              parent=self, pos=wx.Point(824, 104), size=wx.Size(88, 24),
              style=0, value=u'0.0')
        self.TCPaid.SetEditable(False)
        self.TCPaid.Enable(True)

        self.staticText3 = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT3,
              label=u'\u5df2\u6536\u91d1\u989d\uff1a', name='staticText3',
              parent=self, pos=wx.Point(736, 112), size=wx.Size(85, 16),
              style=0)

        self.staticText4 = wx.StaticText(id=wxID_PANELORDERSALESTATICTEXT4,
              label=u'\u672a\u6536\u91d1\u989d\uff1a', name='staticText4',
              parent=self, pos=wx.Point(736, 136), size=wx.Size(85, 16),
              style=0)

        self.TCUnpaid = wx.TextCtrl(id=wxID_PANELORDERSALETCUNPAID,
              name=u'TCUnpaid', parent=self, pos=wx.Point(824, 128),
              size=wx.Size(88, 24), style=wx.TE_READONLY, value=u'0.0')
        self.TCUnpaid.SetForegroundColour(wx.Colour(255, 0, 0))
        self.TCUnpaid.SetEditable(False)
        self.TCUnpaid.Enable(True)
        self.TCUnpaid.SetBackgroundColour(wx.Colour(255, 255, 255))

        self.tBuyer = wx.StaticText(id=wxID_PANELORDERSALETBUYER,
              label=u'\u91c7\u8d2d\u4eba\uff1a', name=u'tBuyer', parent=self,
              pos=wx.Point(384, 96), size=wx.Size(68, 16), style=0)

        self.comboBuyer = wx.ComboBox(choices=[],
              id=wxID_PANELORDERSALECOMBOBUYER, name=u'comboBuyer', parent=self,
              pos=wx.Point(456, 88), size=wx.Size(150, 24),
              style=wx.CB_READONLY, value=u'')
        self.comboBuyer.SetLabel(u'comboBox1')
        self.comboBuyer.Bind(wx.EVT_COMBOBOX, self.OnComboBuyerCombobox,
              id=wxID_PANELORDERSALECOMBOBUYER)

        self.tKeyword = wx.StaticText(id=wxID_PANELORDERSALETKEYWORD,
              label=u'\u5ba2\u6237\u5173\u952e\u5b57\u8bf4\u660e',
              name=u'tKeyword', parent=self, pos=wx.Point(136, 115),
              size=wx.Size(112, 15), style=0)
        self.tKeyword.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL, False,
              u'\u6977\u4f53_GB2312'))
        self.tKeyword.SetBackgroundColour(wx.Colour(255, 255, 0))
        self.tKeyword.SetForegroundColour(wx.Colour(0, 0, 0))
        self.tKeyword.Show(False)

        self.btnDraft = wx.Button(id=wxID_PANELORDERSALEBTNDRAFT,
              label=u'\u5b58\u4e3a\u8349\u7a3f', name=u'btnDraft', parent=self,
              pos=wx.Point(240, 544), size=wx.Size(93, 26), style=0)
        self.btnDraft.Bind(wx.EVT_BUTTON, self.OnBtnDraftButton,
              id=wxID_PANELORDERSALEBTNDRAFT)

        self.tState = wx.StaticText(id=wxID_PANELORDERSALETSTATE,
              label=u'\u72b6\u6001\uff1a', name=u'tState', parent=self,
              pos=wx.Point(384, 480), size=wx.Size(51, 16), style=0)

        self.tcState = wx.TextCtrl(id=wxID_PANELORDERSALETCSTATE,
              name=u'tcState', parent=self, pos=wx.Point(440, 472),
              size=wx.Size(96, 26), style=0, value=u'')

        self.btnSelState = wx.Button(id=wxID_PANELORDERSALEBTNSELSTATE,
              label=u'+', name=u'btnSelState', parent=self, pos=wx.Point(536,
              472), size=wx.Size(24, 26), style=0)
        self.btnSelState.Bind(wx.EVT_BUTTON, self.OnBtnSelStateButton,
              id=wxID_PANELORDERSALEBTNSELSTATE)

        self.btnDeliveryPlan = wx.Button(id=wxID_PANELORDERSALEBTNDELIVERYPLAN,
              label=u'\u9001\u8d27\u8bbe\u7f6e', name=u'btnDeliveryPlan',
              parent=self, pos=wx.Point(384, 136), size=wx.Size(80, 26),
              style=0)
        self.btnDeliveryPlan.Bind(wx.EVT_BUTTON, self.OnBtnDeliveryPlanButton,
              id=wxID_PANELORDERSALEBTNDELIVERYPLAN)

        self.tcDeliveryPlan = wx.TextCtrl(id=wxID_PANELORDERSALETCDELIVERYPLAN,
              name=u'tcDeliveryPlan', parent=self, pos=wx.Point(464, 136),
              size=wx.Size(144, 26), style=0, value=u'')
        self.tcDeliveryPlan.SetEditable(False)
        self.tcDeliveryPlan.Enable(False)

        self.checkBoxDebt = wx.CheckBox(id=wxID_PANELORDERSALECHECKBOXDEBT,
              label=u'\u6253\u5370\u603b\u6b20\u6b3e', name=u'checkBoxDebt',
              parent=self, pos=wx.Point(528, 576), size=wx.Size(105, 16),
              style=0)
        self.checkBoxDebt.SetValue(True)

    def __init__(self, parent):
        self._init_ctrls(parent)

        self.myInit()
        
    def myInit(self):
        self.m_peer = None
        self.clsOrder = CDataSaleOrder
        self.clsDetail = CDataSaleDetail
        
        self.myInitBuyer()
        
        # grid
        self.myInitGrid()
        
        # state matchine
        self.myInitState()
        
        self.myInitPeerWin()
        
        #设置曾经购买的产品列表
        self.lcHistory = MyListCtrlCustProRecent(self, pos=wx.Point(736, 176),size=wx.wx.Size(400, 360))
        # 141012 初始化时默认了 DefaultPosition, DefaultSize，
        #        移动会导致会导致lc位置大小闪烁
        #self.lcHistory.Move(wx.Point(760, 200))
        #self.lcHistory.SetSize(wx.Size(400, 360))
        self.lcHistory.Bind(wx.EVT_LEFT_DCLICK, self.OnLcHistoryProLeftDclick)
    
        #经手人
        self.cbHandler = MyComboBoxDecorator(self.comboStaff, CDataStaff, CDataStaff.COL_NAME)
        self.cbHandler.refresh()
        self.cbHandler.SetValue(Cfg.getCurUser().getValue(CDataStaff.COL_NAME))
        
        self.TCCustomer.SetFocus()
        
        self.dateSO.SetValue(wx.DateTime.Today())
        self.refreshBillId()
    
        self.enableAll(False)
        self.TCCustomer.Enable()
        self.btnShowCustomer.Enable()
        
    def myInitBuyer(self):
        self.newBuyer = u'新增联系人'
        #self.comboBuyer.Append(self.newBuyer)
        
    def resetBuyer(self, peerId=-1):
        if (peerId == -1):
            peerId = self.m_peer.getValue(self.m_peer.COL_ID)
            
        self.comboBuyer.Clear()
        self.comboBuyer.Append('')
        
        list = CDataCustomerContact.getContactText(peerId)
        for item in list:
            self.comboBuyer.Append(item)
            
        self.comboBuyer.Append(self.newBuyer)
        
    def myInitPeerWin(self):
        self.pWin = DlgCustomerChoice.create(self)
        self.tcPeer = MyPopupTextCtrlDecorator(self.TCCustomer, self.pWin)
        
    def myInitGrid(self):
        titles = [(u'编号', 0),
                    (u'产品', 160), 
                    (u'规格', 0),
                    (u'单位', 50), 
                    (u'数量', 70), 
                    (u'单价',70), 
                    (u'小计',100),
                    (u'备注', 170)]
        [self.COL_PROID , self.COL_PRONAME, self.COL_PROSPEC, self.COL_UNIT, self.COL_CNT,
        self.COL_PRICE, self.COL_TOTAL, self.COL_MEMO] = [i for i in range(len(titles))]         
        
        self.grid.CreateGrid(0, len(titles))
        
        # 设置列宽为0总是不生效，后来发现检视器中设置了最小15，改成最小0就可以了
        #self.grid.SetDefaultColSize(0,True)
        #print self.grid.GetDefaultColSize()
        
        for i in range(len(titles)):
            #self.grid.SetColMinimalWidth(i,0)
            self.grid.SetColLabelValue(i, titles[i][0])
            self.grid.SetColSize(i, titles[i][1])
            #print (titles[i][1],self.grid.GetColSize(i), self.grid.GetDefaultColSize())
        self.grid.SetSelectionMode(wx.grid.Grid.wxGridSelectRows)
        
        #self.grid.HideCol(self.COL_PROID)
        
        # 貌似一个col只能SetColAttr一次，两次会运行终止
        attr = wx.grid.GridCellAttr()
        attr.SetReadOnly(True)
        attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
        attr.SetBackgroundColour(wx.LIGHT_GREY)
        self.grid.SetColAttr(self.COL_PROID, attr)
        self.grid.SetColAttr(self.COL_UNIT, attr)
        self.grid.SetColAttr(self.COL_TOTAL, attr)
        self.grid.SetColAttr(self.COL_PROSPEC, attr)
        
        # 如果不是新建attr，表现会很奇怪，COL_PROID也变成了.00
        attr = wx.grid.GridCellAttr()
        #attr.SetReadOnly(False)
        #attr.SetRenderer(wx.grid.GridCellFloatRenderer(precision=2))
        attr.SetEditor(wx.grid.GridCellFloatEditor(precision=2))
        attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
        self.grid.SetColAttr(self.COL_CNT, attr)
        self.grid.SetColAttr(self.COL_PRICE, attr)
        #self.grid.SetColAttr(self.COL_TOTAL, attr) #出现内存不能read错误

        
        # 运行出错
##        attr = wx.grid.GridCellAttr()
##        attr.SetAlignment(wx.ALIGN_RIGHT, wx.ALIGN_CENTRE)
##        self.grid.SetColAttr(self.COL_CNT, attr)
##        self.grid.SetColAttr(self.COL_PRICE, attr)
##        self.grid.SetColAttr(self.COL_TOTAL, attr)
        
        #添加右键菜单
        self.menu = wx.Menu()
        
        item = self.menu.Append(-1, u'添加商品')
        self.Bind(wx.EVT_MENU, self.OnMenuAdd, item)
        
        item = self.menu.Append(-1, u'删除商品')
        self.Bind(wx.EVT_MENU, self.OnMenuDelRow, item)
        
        item = self.menu.Append(-1, u'新商品')
        self.Bind(wx.EVT_MENU, self.OnMenuNewPro, item)
        
        #item = self.menu.Append(-1, u'添加新行')
        #self.Bind(wx.EVT_MENU, self.OnMenuNewRow, item)
        
        self.grid.GetGridWindow().Bind(wx.EVT_RIGHT_UP, self.OnGridRightUp)
        
    def refreshBillId(self):
        if self.isModify():
            # 150902 编辑模式禁止修改ID，否则ID变化会导致相关表要求同步修改，复杂度高，健壮性差
            return
        
        #date = self.dateSO.GetValue().Format('%Y%m%d')
        #id = self.clsOrder.newId(date)
        #self.tBillId.SetLabel(id)
    
    def myInitState(self):
        self.bSaved = False
        self.STATE_NEW = 0
        self.STATE_MODIFY = 1
        self.curState = self.STATE_NEW #default state
        self.editedBillId = ''
    
    def isModify(self):
        return self.curState == self.STATE_MODIFY
    
    def refreshAmount(self):
        '''待售商品数量、价格变化时，刷新总金额'''
        amount = 0
        for i in range(self.grid.GetNumberRows()):
            amount += float(self.grid.GetCellValue(i, self.COL_TOTAL))
 
        self.tcYingShou.SetValue(kit.myStr(amount))
    
    def getGridData(self):
        '''return - [[proId, proName, proSpec,unit, cnt, price, total], [...], ...]'''
        proOnsale = []
        for row in range(self.grid.GetNumberRows()):
            dataRow = []
            for col in range(self.grid.GetNumberCols()):
                dataRow.append(self.grid.GetCellValue(row, col))

            proOnsale.append(dataRow)
            
        return proOnsale
    
    def appendGrid(self, dataList):
        '''dataList - [[proId, proName, proSpec,unit, cnt, price, total], [...], ...]'''
        #print dataList
        grid = self.grid
        for i in range(len(dataList)):
            row = grid.GetNumberRows()
            grid.AppendRows()
            for col in range(len(dataList[0])):
                grid.SetCellValue(row, col, kit.myStr(dataList[i][col]))
        
        # 添加新数据后，自动重新计算总金额                    
        self.refreshAmount()
    
    def updateCustomer(self):
        if self.isModify():
            self.m_peer.setValue(self.m_peer.COL_LASTORDER, self.dateSO.GetValue().Format('%Y-%m-%d'))
            self.m_peer.update()
    
    def getSelectPeer(self):
        return self.m_peer
    
    def setSelectPeer(self, obj):
        '''选择销售客户，更改客户需要清空当前的数据
            @param
            obj - customer selected 
        '''
        #clear some data input before
        #self.gridSOProList.DeleteRows(numRows=self.gridSOProList.GetNumberRows()-1)
        
        self.m_peer = obj
        
        custName = obj.getValue(obj.COL_NAME)
        
        title = u'【销】%s' %custName
        #self.SetTitle(title)
        book = self.GetParent()
        self.GetParent().SetPageText(book.GetSelection(), title)
        
        #设置客户名称，采用changevalue()避免产生新事件    
        #self.TCCustomer.SetValue(obj.getFieldVal(field='name'))
        self.TCCustomer.ChangeValue(custName)
        
        #customer id
        id = obj.getValue(obj.COL_ID)
        
        #设置送货地址
        print 'TODO:delivery info'
        self.dlvyChoices = []
        self.dlvyObjList = CRelCustDlvy.getDlvy(id)
        for dlvyObj in self.dlvyObjList:
            dlvyName = dlvyObj.getFieldVal(index=CDataDelivery.COL_NAME)
            self.dlvyChoices.append(dlvyName)
            self.comboDelivery.Append(dlvyName)
        
        #设置消费记录
        total = obj.getSaleAmount() + obj.getInitDebt()
        paid = obj.getPaidAmount()
        self.TCTotal.SetValue(str(total))
        self.TCPaid.SetValue(str(paid))
        self.TCUnpaid.SetValue(str(total - paid))

        #设置曾经购买的产品列表
        self.lcHistory.refresh({'peerId':id})
    
        self.resetBuyer(id)
        
        # 141227 - 设置客户关键字
        keywords = CDataCustomerLabeling.getKeyword(self.m_peer.getValue(self.m_peer.COL_ID))
        if keywords:
            self.tKeyword.SetLabel(kit.concat(keywords, ','))
            self.tKeyword.Show()
        else:
            self.tKeyword.Show(False)
        
        self.enableAll()
        self.btnPayment.Enable(False)
        self.btnPrint.Enable(False)
            
    def OnLcHistoryProLeftDclick(self, event):
        '''左键双击直接选择曾经购买的商品'''
        
        item = self.lcHistory.GetNextItem(-1, state = wx.LIST_STATE_SELECTED)
        if (item == -1):
            return

        proId,proName,proSpec,unit,price = self.lcHistory.getProSaleInfo(item)
        
        self.appendGrid([[proId, proName, proSpec,unit, 0.0, price, 0.0]])
##        dlg = DlgProGX(self)
##        dlg.setData(proId=proId, unit=unit, price=price)
##        dlg.setInbound(False)
##        if (dlg.ShowModal() == wx.ID_OK):
##
##            unit = dlg.unit
##            cnt = dlg.cnt
##            price = dlg.price
##            total = dlg.cnt*dlg.price
##            data = []
##            data.append([proId, proName, unit, cnt, price, total])
##            
##            for unit,cnt in dlg.lonelyUnit.items():
##                data.append([str(proId), proName, unit, str(cnt), 0.0, 0.0])
##                
##            self.appendGrid(data)
            
    def OnGridRightUp(self, event):
        '''右键菜单弹出'''
        self.grid.GetGridWindow().PopupMenu(self.menu, event.GetPosition())
    
    def OnMenuAdd(self, event):
        '''右键菜单选中<添加已有商品>'''
        #dlg = DlgSelectPro.create(self.GetParent(), DlgSelectPro.TypeSale, self.m_peer)
        dlg = DlgSelectPro.create(None, DlgSelectPro.TypeSale, self.m_peer)
        dlg.appendProDetail(self.getGridData())    
        
        print(self.GetParent().GetSelection())
        sel = self.GetParent().GetSelection()
                        
        if(dlg.ShowModal() == wx.ID_OK):
            numRows=self.grid.GetNumberRows()
            if(numRows > 0):
                self.grid.DeleteRows(numRows=numRows)
            self.appendGrid(dlg.getProSaleList())
        
        print(self.GetParent().GetSelection())
        self.GetParent().SetSelection(sel)
        
    def OnMenuNewPro(self, event):
        '''右键菜单选中<添加新商品>'''
        dlg = DlgEditPro.create(self)
        if (dlg.ShowModal() == wx.ID_OK):
            proObj = dlg.getProObj()
            
            proId = proObj.getValue(proObj.COL_ID)
            proName = proObj.getValue(proObj.COL_NAME)
            unit = proObj.getValue(proObj.COL_UNIT1)
            cnt = 0.0
            price = proObj.getValue(proObj.COL_DEFSALE1)
            total = kit.myFloat(cnt) * kit.myFloat(price)
            self.appendGrid([[proId, proName, unit, cnt, price,total]])
        
            self.grid.SetFocus()
            row = self.grid.GetNumberRows() - 1
            self.grid.SetGridCursor(row, self.COL_CNT)
            
    def OnMenuDelRow(self, event):
        '''右键菜单选中<删除选中行>'''
        rows = self.grid.GetSelectedRows()
        rows.sort(reverse=True)
        for index in range(len(rows)):
            self.grid.DeleteRows(rows[index])
        # 避免可能的多个选中导致的循环删除时错删
        #self.gridSOProList.DeleteRows(rows[0])
        self.refreshAmount()

    def OnBtnShowCustomerButton(self, event):
        self.tcPeer.resetPopupWinPos()
        self.pWin.Show()

    def OnDateSODateChanged(self, event):
##        if (self.isModify()):
##            msg = u'改变日期会导致单据编号发生变化，原来针对此订单的收款等信息将丢失，'\
##                    u'是否继续修改？'
##            dlg = wx.MessageDialog(self, msg,u'提示',wx.YES_NO|wx.ICON_QUESTION)
##            if(dlg.ShowModal() == wx.ID_NO):
##                return
            
        self.refreshBillId()
        
        event.Skip()

    def OnGridSOProListGridCellChange(self, event):
        '''改变<单价><数量>时，重新计算<小计><应收金额>'''
        if (event.GetCol() < self.COL_CNT):
            #cnt\price unchanged
            return
        
        row = event.GetRow()
        
        if (event.GetCol() == self.COL_TOTAL):
            cnt = float(self.grid.GetCellValue(row, self.COL_CNT))
            total = float(self.grid.GetCellValue(row, self.COL_TOTAL))
            price = total / cnt
            if (price == round(price, 2)):
                self.grid.SetCellValue(row, self.COL_PRICE, str(price))
            else:
                msg = u'单价不能自动计算为货币数值，请手动调整单价或设置优惠金额'
                dlg = wx.MessageDialog(self, msg,u'提示',wx.OK|wx.ICON_INFORMATION)
                dlg.ShowModal()
            
        try:
            total = float(self.grid.GetCellValue(row, self.COL_CNT)) * \
                        float(self.grid.GetCellValue(row, self.COL_PRICE))
            self.grid.SetCellValue(row, self.COL_TOTAL, str(total))
        
            self.refreshAmount()
        except ValueError,e:
            #print e
            msg = u'发生错误：%s\n输入错误：请输入数值' %e
            dlg = wx.MessageDialog(self, msg,u'提示',wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            # 150125 - 会导致错误循环
            #self.grid.SetGridCursor(row, event.GetCol())
            
    def OnGridSOProListGridSelectCell(self, event):
        self.grid.SelectRow(event.GetRow())
        # 必须保留，以便选中Cell可以进入可编辑状态
        event.Skip()

    def OnGridSOProListGridCellRightClick(self, event):
        self.grid.SelectRow(event.GetRow())
        event.Skip()

    def audit_check(self):
        if self.m_billObj.isAudited():
            self.enableAll(False)
            
            dlg = wx.MessageDialog(self, u'订单已经审核过，不允许编辑，如需编辑，请首先反审核',
                                    u'提示',wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
        
    def loadBill(self, billId):
        # 该处代码使用fetch获取object，导致该对象update时CDataSaleOrder.m_dataList中的缓存没有更新
        # 也就是说只有使用fetch获取db数据的才是新数据，从m_dataList中获取的是过时数据
        # 编辑功能都要注意检查这个问题
        #sql = "id='%s'" %billId
        #objs = self.clsOrder.fetch(sql)
        #if (len(objs) != 1):
        #    print 'Error incorrect saleId:%s' %billId
        #assert len(objs) == 1
        #billObj = objs[0]
        self.m_billObj = self.clsOrder.findObj(billId)        
        billObj = self.m_billObj
        
        billId = billObj.getValue(billObj.COL_ID)
        peerId = billObj.getValue(billObj.COL_PEERID)
        peerObj = CDataCustomer.getFirstInstance({CDataCustomer.COL_ID:peerId})
        
        self.setSelectPeer(peerObj)
        
        self.tBillId.SetLabel(billId)
        self.tBillId.Show()

        date = billObj.getValue(billObj.COL_BILLDATE)
        self.dateSO.SetValue(wx.DateTimeFromDMY(date.day, date.month-1, date.year,0,0,0))

        buyer = billObj.getValue(billObj.COL_BUYER)
        if(buyer is None):
            buyer = ''
        self.comboBuyer.SetValue(buyer)
        
        #self.comboDelivery.SetStringSelection(billObj.getValue(billObj.COL_DLVYADDR))
        #dlvyId = billObj.getValue(billObj.COL_DLVYID)
        #dlvyObj = CDataDelivery.findObj(dlvyId)
        #self.comboDelivery.SetStringSelection(dlvyObj.getValue(dlvyObj.COL_NAME))
        dlvyAddr = billObj.getDlvyAddr()
        if dlvyAddr:
            self.comboDelivery.SetStringSelection(dlvyAddr)
        
        self.tcYingShou.SetValue(str(billObj.getValue(billObj.COL_TOTAL)))
        self.tcShiShou.SetValue(str(billObj.getPaid()))
        self.tcYouHui.SetValue(str(billObj.getValue(billObj.COL_DISCOUNT)))

        hId = billObj.getValue(billObj.COL_HANDLERID)
        hObj = CDataStaff.getFirstInstance({CDataStaff.COL_ID:hId})
        self.cbHandler.SetValue(hObj.getValue(hObj.COL_NAME))
        
        self.tcMemo.SetValue(billObj.getValue(billObj.COL_MEMO))
        
        state = billObj.getValue(billObj.COL_STATE)
        if(state is None):
            state = ''
        self.tcState.SetValue(state)
        
        self.tcDeliveryPlan.SetValue(billObj.getDeliveryPlan())
    
        # 170107 - 增加审核功能
        self.audit_check()
        
    def loadBillDetail(self, billId):
        '''把销售产品明细显示到grid'''
        self.appendGrid(self.clsOrder.getProDetail(billId))
    
    def setEditBill(self, billId, draft=False):
        '''设置要编辑的订单数据'''
        print(u'编辑订单', billId)
        self.curState = self.STATE_MODIFY
        self.btnPayment.Enable(False)
        
        self.bDraft = draft
        if (self.bDraft):
            self.clsOrder = CDataSaleOrderTemp
            self.clsDetail = CDataSaleDetailTemp
        else:
            self.clsOrder = CDataSaleOrder
            self.clsDetail = CDataSaleDetail
            self.btnDraft.Enable(False)
            
        self.editedBillId = billId
        self.loadBill(billId)
        self.loadBillDetail(billId)
        
    def enableAll(self, enable=True):
        self.TCCustomer.Enable(enable)
        self.btnShowCustomer.Enable(enable)
        self.dateSO.Enable(enable)
        self.comboDelivery.Enable(enable)
        
        #self.btnAddPro.Enable(enable)
        #self.btnNewPro.Enable(enable)
        #self.btnDelPro.Enable(enable)
        self.grid.Enable(enable)
        
        self.tcMemo.Enable(enable)
        
        self.comboStaff.Enable(enable)
        self.tcYouHui.Enable(enable)
        
        self.btnSave.Enable(enable)
        self.btnDraft.Enable(enable)
        self.btnPayment.Enable(enable)
        self.btnHistory.Enable(enable)
        self.btnPrint.Enable(enable)
        
        self.comboBuyer.Enable(enable)
        
        self.btnDeliveryPlan.Enable(enable)
        
        self.tcState.Enable(enable)
        self.btnSelState.Enable(enable)
        
    def disableEdit(self):
        self.enableAll(False)
##        self.TCCustomer.Disable()
##        self.btnShowCustomer.Disable()
##        self.dateSO.Disable()
##        self.comboDelivery.Disable()
##        
##        self.btnAddPro.Disable()
##        self.btnNewPro.Disable()
##        self.btnDelPro.Disable()
##        self.grid.Disable()
##        
##        self.tcMemo.Disable()
##        
##        self.comboStaff.Disable()
##        self.tcYouHui.Disable()
##        
##        self.btnSave.Disable()
##        self.btnDraft.Disable()
##        self.btnPayment.Disable()
##        self.btnHistory.Disable()
##        
##        self.comboBuyer.Disable()
        
    def saveDelivery(self):
        dlvyName = self.comboDelivery.GetValue()
        if (dlvyName == ''):       
            return 1
        
        dlvyId = -1
        for i in range(len(self.dlvyObjList)):
            if dlvyName == self.dlvyObjList[i].getFieldVal(index=CDataDelivery.COL_NAME):
                dlvyId = self.dlvyObjList[i].getFieldVal(index=CDataDelivery.COL_ID)
                return 1
                
        #如果配送地址是新的，则添加到数据库        
        if dlvyId == -1:
            #添加新的配送方式
            
            #dlvyId = CDataDelivery.newAutoIncrId()
            #print '********newid %d***********' %dlvyId
            newDlvy = CDataDelivery.factory()
            newDlvy.setMulFieldVal({CDataDelivery.COL_NAME:dlvyName})
            newDlvy.insert()
            dlvyId = newDlvy.getValue(newDlvy.COL_ID)
            
            #添加新的客户-配送关系
            newCustDlvy = CRelCustDlvy.factory()
            newCustDlvy.setMulFieldVal({CRelCustDlvy.COL_CUSTID:self.m_peer.getValue(self.m_peer.COL_ID), 
                                    CRelCustDlvy.COL_DLVYID:dlvyId})
            return newCustDlvy.insert()
    
    def getBillData(self):
        clsOrder = self.clsOrder
        data = {}
        
        if self.isModify():
            data[clsOrder.COL_ID] = self.m_billObj.getValue(self.m_billObj.COL_ID)
            
        data[clsOrder.COL_PEERID] = self.m_peer.getValue(self.m_peer.COL_ID)
        
        dlvyObj = CDataDelivery.getFirstInstance({CDataDelivery.COL_NAME:self.comboDelivery.GetValue()})
        if dlvyObj:
            data[clsOrder.COL_DLVYID] = dlvyObj.getValue(dlvyObj.COL_ID)
                
        data[clsOrder.COL_BILLDATE] = self.dateSO.GetValue().Format('%Y-%m-%d')
        
        data[clsOrder.COL_TOTAL] = float(self.tcYingShou.GetValue())

        data[clsOrder.COL_DISCOUNT] = float(self.tcYouHui.GetValue())
        
        data[clsOrder.COL_HANDLERID] = self.cbHandler.getSelectObj().getValue(CDataStaff.COL_ID)
        data[clsOrder.COL_RECOREDERID] = Cfg.getCurUser().getValue(CDataStaff.COL_ID) 
        
        data[clsOrder.COL_MEMO] = self.tcMemo.GetValue()
        data[clsOrder.COL_BUYER] = self.comboBuyer.GetValue()
        data[clsOrder.COL_STATE] = self.tcState.GetValue()
        
        if self.tcDeliveryPlan.GetValue():
            data[clsOrder.COL_DELIVERYPLAN] = self.tcDeliveryPlan.GetValue()
        else:
            data[clsOrder.COL_DELIVERYPLAN] = None
                
        data[clsOrder.COL_MODIFYTIME] = datetime.datetime.now()
        
        return data
    
    def getBillDetail(self):
        detail = []
        for i in range(self.grid.GetNumberRows()):
            #billId = self.tBillId.GetLabel()
            billId = self.m_billObj.getValue(self.m_billObj.COL_ID)
            peerId = self.m_peer.getValue(self.m_peer.COL_ID)

            proId = int(self.grid.GetCellValue(i, 0))
            proName = self.grid.GetCellValue(i, 1)
            unit = self.grid.GetCellValue(i, 2)
            num = float(self.grid.GetCellValue(i, 3))
            price = float(self.grid.GetCellValue(i, 4))
            total = float(self.grid.GetCellValue(i, 5))
            memo = self.grid.GetCellValue(i, self.COL_MEMO)
            
            clsDetail = self.clsDetail            
            data = {clsDetail.COL_BILLID:billId, 
                clsDetail.COL_PEERID:peerId, 
                clsDetail.COL_PROID:proId,
                clsDetail.COL_PRONAME:proName,
                clsDetail.COL_UNIT:unit,
                clsDetail.COL_NUM:num, 
                clsDetail.COL_PRICE:price, 
                clsDetail.COL_TOTAL:total,
                clsDetail.COL_MEMO:memo}
                
            detail.append(data)
            
        return detail
    
    def saveBill(self):        
        '''保存订单信息'''
        #billId = self.tBillId.GetLabel()
        if self.isModify():
            #billId = self.tBillId.GetLabel()
            billId = self.m_billObj.getValue(self.m_billObj.COL_ID)
        else:
            id,billId = self.clsOrder.generateId(self.dateSO.GetValue().Format('%Y%m%d'))
         
        peerId = self.m_peer.getValue(self.m_peer.COL_ID)
        
        dlvyAddr = self.comboDelivery.GetValue()
        dlvyId = None
        if dlvyAddr:
            dlvyObj = CDataDelivery.getFirstInstance({CDataDelivery.COL_NAME:dlvyAddr})
            dlvyId = dlvyObj.getValue(dlvyObj.COL_ID)
        
        # 把unicode转换为date类型，以免编辑出错
        # 以前使用fetch没用缓存，所以没发现这个错误
        # 思考：应该由界面控制dataModle<->view的数据类型转换还是由dataModle控制？
        # 应该是界面控制好一些，因为不同的view知道底层数据是什么样子的，而data不知道view会做成什么样子
        billDate = kit.str2Date(self.dateSO.GetValue().Format('%Y-%m-%d'))
        #billDate = self.dateSO.GetValue().Format('%Y-%m-%d')
        
        total = float(self.tcYingShou.GetValue())
        paid = float(self.tcShiShou.GetValue())
        discount = float(self.tcYouHui.GetValue())
        unpaid = total - paid - discount
        
        handlerId = self.cbHandler.getSelectObj().getValue(CDataStaff.COL_ID)
        
        memo = self.tcMemo.GetValue()
        buyer = self.comboBuyer.GetValue()
        
        clsOrder = self.clsOrder
        data = {clsOrder.COL_ID:billId, 
                clsOrder.COL_PEERID:peerId,
                clsOrder.COL_DLVYID:dlvyId,
                clsOrder.COL_BILLDATE:billDate,
                clsOrder.COL_TOTAL:total, 
                #clsOrder.COL_PAID:paid,
                #clsOrder.COL_UNPAID:unpaid,
                clsOrder.COL_DISCOUNT:discount, 
                clsOrder.COL_HANDLERID:handlerId, 
                clsOrder.COL_MEMO:memo,
                clsOrder.COL_BUYER:buyer,
                clsOrder.COL_STATE:self.tcState.GetValue()}
        
        if self.tcDeliveryPlan.GetValue():
            data[clsOrder.COL_DELIVERYPLAN] = self.tcDeliveryPlan.GetValue()
        else:
            data[clsOrder.COL_DELIVERYPLAN] = None
        
        if self.isModify():
            data[clsOrder.COL_UPDATER] = Cfg.getCurUser().getValue(CDataStaff.COL_ID) 
            data[clsOrder.COL_UPDATETIME] = datetime.datetime.now()
            data[clsOrder.COL_UPDATECNT] = self.m_billObj.getValue(self.m_billObj.COL_UPDATECNT) + 1
        else:
            data[clsOrder.COL_RECOREDERID] = Cfg.getCurUser().getValue(CDataStaff.COL_ID) 
            data[clsOrder.COL_CREATETIME] = datetime.datetime.now()
            
            
        if(self.isModify() and not self.bDraft):
            self.m_billObj.setMulFieldVal(data)
            return self.m_billObj.update()
        else:
            obj = clsOrder.factory(False)
            obj.setMulFieldVal(data)
            ret = obj.insert()
            self.m_billObj = obj
            return ret
    
    def saveDetail(self):
        '''保存销售明细'''
        for i in range(self.grid.GetNumberRows()):
            #billId = self.tBillId.GetLabel()
            billId = self.m_billObj.getValue(self.m_billObj.COL_ID)
            peerId = self.m_peer.getValue(self.m_peer.COL_ID)

            proId = int(self.grid.GetCellValue(i, self.COL_PROID))
            proName = self.grid.GetCellValue(i, self.COL_PRONAME)
            unit = self.grid.GetCellValue(i, self.COL_UNIT)
            num = float(self.grid.GetCellValue(i, self.COL_CNT))
            price = float(self.grid.GetCellValue(i, self.COL_PRICE))
            total = float(self.grid.GetCellValue(i, self.COL_TOTAL))
            memo = self.grid.GetCellValue(i, self.COL_MEMO)
            
            clsDetail = self.clsDetail            
            data = {clsDetail.COL_BILLID:billId, 
                clsDetail.COL_PEERID:peerId, 
                clsDetail.COL_PROID:proId,
                clsDetail.COL_PRONAME:proName,
                clsDetail.COL_UNIT:unit,
                clsDetail.COL_NUM:num, 
                clsDetail.COL_PRICE:price, 
                clsDetail.COL_TOTAL:total,
                clsDetail.COL_MEMO:memo}
            
               
            item = clsDetail.factory(False)
            item.setMulFieldVal(data)
            print ('insert detail:', item)
            cnt = item.insert()
            if(cnt <= 0):
                return cnt
        
        return 1 
    
    def checkProStock(self):
        import DlgProMulUnitAdjust
        #print 'checkProStock'
        list = []
        for i in range(self.grid.GetNumberRows()):
            proId = int(self.grid.GetCellValue(i, self.COL_PROID))
            proName = self.grid.GetCellValue(i, self.COL_PRONAME)
            unit = self.grid.GetCellValue(i, self.COL_UNIT)
            #num = float(self.grid.GetCellValue(i, 3))
            #for i in range(proObj.UNIT_CNT):
            #    ratio = self.COL_RATIO1 + i * self.UNIT_CNT
            proObj = CDataProduct.findObj(proId)
            for val in proObj.getUnratioUnit(unit):
                list.append([proId, proName,val])
##            unitDict = proObj.getUnitDict()
##            print unitDict
##            if unitDict[unit][0]:
##                for key in unitDict.keys():
##                    if key == unit:
##                        continue
##                    else:
##                        if unitDict[key][0] is None or unitDict[key][0] == '':
##                            list.append([proId, proName,key])
##            else:
##                for key in unitDict.keys():
##                    if key == unit:
##                        continue
##                    else:
##                        if unitDict[key][0]:
##                            list.append([proId, proName, key])
        
        #print list
        if list:
            dlg = DlgProMulUnitAdjust.DlgProMulUnitAdjust(self)
            dlg.appendData(list)
            dlg.ShowModal()
    
    def updateSaleOrder(self, bill, detail, insert=False):
        pass
    
    def dataValidate(self):
        
        if (self.grid.GetNumberRows() <= 0):
            dlg = wx.MessageDialog(self, u'订单未完成：未选择产品',u'提示',wx.OK|wx.ICON_ERROR)
            dlg.ShowModal()
            return False
        
        
        
        return True
        
                
    def trySave(self):
                
        #if not dataValidate():
        #    return False
        
        try:
            dbmngr.dbmngr.beginTrans()
            
            if(self.saveDelivery() <= 0):
                msg = u'配送信息保存出现问题，请查找原因！'
                dlg = wx.MessageDialog(self, msg,u'提示',wx.OK|wx.ICON_ERROR)
                dlg.ShowModal()
                # 141014 非关键问题，仅提示不阻塞，以便正常使用其他功能
                #return
            
            # 现在的问题是，修改时delBill\Detail->insertBill\Detail,del导致引用ID的表会出异常
            # 现在的计划是，禁止修改ID，修改操作改为deDetail->updateBill\insertDetail,
            # 这样就不必删除订单了，不会导致ID引用导致的数据库异常 
            
            # 以后的设计是,计划用getBillData\getBillDetail替换saveBill\saveDetail,直接把界面数据
            # 传递给order类，由其决定保存（这个设计要在数据库管理模块把表、对象分离后才方便进行） 
            # 这个设计可以再django版本时实现
                            
            if(self.isModify()):
                if (self.bDraft):
                    CDataSaleOrderTemp.deleteBill(self.editedBillId)
                else:
                    # 150902 禁止修改ID，以免出现混乱
                    #self.clsOrder.deleteBill(self.editedBillId, False)
                    self.clsOrder.clearDetail(self.editedBillId)
                    #assert self.editedBillId == self.tBillId.GetLabel()
##                    if (self.editedBillId != self.tBillId.GetLabel()):
##                        self.clsOrder.deleteBill(self.editedBillId)
##                    else:
##                        self.clsOrder.deleteBill(self.editedBillId, False)
                        
            print 'try to saveBill'
            if(self.saveBill() <= 0):
                msg = u'订单保存失败，请查找原因！'
                #dlg = wx.MessageDialog(self, msg,u'提示',wx.OK|wx.ICON_ERROR)
                #dlg.ShowModal()
                #return False
                raise Exception(msg) # 逻辑上讲不应该return，会导致rollback无法执行
            
            print 'try to saveDetail'
            if(self.saveDetail() <= 0):
                msg = u'订单信息保存成功，但是产品明细保存失败，请联系开发者查找原因！'
                #dlg = wx.MessageDialog(self, msg,u'提示',wx.OK|wx.ICON_ERROR)
                #dlg.ShowModal()
                #return False
                raise Exception(msg) # 逻辑上讲不应该return，会导致rollback无法执行
            
            print 'saveDetail OK'
            # 150502 - 在选择产品时，设置多单位
            #self.checkProStock()
        
            dbmngr.dbmngr.commitTrans()
        
        except Exception as e:
            import traceback
            traceback.print_exc()
        
            print e           
            dbmngr.dbmngr.rollbackTrans(e)
            return False
            
        return True
        
    def saveDraft(self):
        self.clsOrder = CDataSaleOrderTemp
        self.clsDetail = CDataSaleDetailTemp
        
        self.bSaved = self.trySave()
        return self.bSaved
    
    def OnBtnDraftButton(self, event):
        if (self.saveDraft()):
            self.enableAll(False)
            #self.btnPrint.Enable()
            self.btnHistory.Enable()          
    
    def saveOrder(self):
        self.clsOrder = CDataSaleOrder
        self.clsDetail = CDataSaleDetail
        self.bSaved = self.trySave() 
        return self.bSaved
        
    def OnBtnSaveButton(self, event):
        '''保存订单'''
        
        if (self.saveOrder()):
            self.updateCustomer()
            
            self.enableAll(False)
            self.btnPayment.Enable()
            self.btnPrint.Enable()
            self.btnHistory.Enable()

    def OnBtnPaymentButton(self, event):
        if not (self.bSaved):
            dlg = wx.MessageDialog(self, u'请先保存单据，然后再进行收款',u'提示',wx.OK|wx.ICON_INFORMATION)
            dlg.ShowModal()
            return
        
        import DlgVoucher
        dlg = DlgVoucher.DlgVoucher(self, DlgVoucher.Type_Customer)
        #saleId = self.tBillId.GetLabel()
        saleId = self.m_billObj.getValue(self.m_billObj.COL_ID)
        dlg.setBill(saleId, False)
        #dlg.setCustMode(self.customer, self.tcYingShou.GetValue(), self.TSOID.GetLabel())
        if(dlg.ShowModal() == wx.ID_CANCEL):
            return

        self.btnPayment.Disable()
        self.tcShiShou.SetValue(str(dlg.getMoney()))
        # 忘记这一行是为什么在这里了，可能是为了同步，但是已经没必要，因为notify
        #self.m_billObj.collect(dlg.getMoney())

    def OnBtnPrintButton(self, event):
        if not (self.bSaved):
            dlg = wx.MessageDialog(self, u'请先保存单据，然后再进行打印',u'提示',wx.OK|wx.ICON_INFORMATION)
            dlg.ShowModal()
            return
        
        MyPrinter.printSaleOrder(self, self.m_billObj.getValue(self.m_billObj.COL_ID), self.checkBoxDebt.GetValue())

    def quit(self,  doQuit=True):
        if  doQuit:        
            book = self.GetParent()
            book.DeletePage(book.GetSelection())
        return True
    
    def doClose(self, doQuit=True):
        return self.close(doQuit)
    
    def close(self, doQuit=True):
        if self.m_peer is None:
            return self.quit(doQuit)
        
        if (not self.bSaved):
            if (self.curState == self.STATE_MODIFY):
                msg = u'订单没有保存，退出后修改的内容将不会保存，是否继续退出?'
            else:
                msg = u'订单没有保存，退出后将丢失当前数据，是否继续退出?'
            dlg = wx.MessageDialog(self, msg,u'提示',wx.YES_NO|wx.ICON_QUESTION)
            if(dlg.ShowModal() == wx.ID_YES):
                #self.Destroy()
                return self.quit(doQuit)
            else:
                return False
        
        if (self.curState == self.STATE_MODIFY):
            # 修改模式不进行收款测试，直接退出
            #self.Destroy()
            return self.quit(doQuit)
        
        # 141208 - 提醒太麻烦，暂时隐藏 
        alarm = False
        if (alarm):   
            paid = float(self.tcShiShou.GetValue())
            if (paid == 0.0 and self.btnPayment.IsEnabled() and self.btnPayment.IsShown()):
                dlg = wx.MessageDialog(self, u'该订单没有收款信息，是否继续退出?',u'提示',wx.YES_NO|wx.ICON_QUESTION)
                if(dlg.ShowModal() == wx.ID_NO):
                    return False
            
            # event alarm:debt
            amount = float(self.tcYingShou.GetValue())
            discount = float(self.tcYouHui.GetValue())
            debt = amount-paid-discount
            if (debt > 0.0):
                msg = u'该订单欠款%.2f元，是否添加到开机提醒?' %debt
                dlg = wx.MessageDialog(self, msg,u'提示',wx.YES_NO|wx.ICON_QUESTION)
                if(dlg.ShowModal() == wx.ID_YES):
                    title = u'【%s】的订单【%s】欠款%.2f元' \
                            %(self.customer.getValue(CDataCustomer.COL_NAME),
                            self.TSOID.GetLabel(),
                            debt)
                    self.addEventAlert(title, title)
        #self.Destroy()
        return self.quit(doQuit)
        
    def addEventAlert(self, title, content):
        import DlgEventEditor
        dlg = DlgEventEditor.create(self)
        dlg.setData(title, content)
        dlg.ShowModal()
            
    def OnBtnCancelButton(self, event):
        self.close()

    def OnBtnHistoryButton(self, event):
        if (self.m_peer is None):
            return
        
        kit.getRootWin(self).showCustFund(self.m_peer)
        
        
##        import DlgFundCustomer
##        dlg = DlgFundCustomer.create(self)
##        dlg.Show()
##        dlg.setCustomer(self.m_peer)
##        dlg.refresh()

    def OnComboBuyerCombobox(self, event):
        import DlgEditorContact
        if(self.comboBuyer.GetValue() == self.newBuyer):
            dlg = DlgEditorContact.create(self)
            if (dlg.ShowModal() == wx.ID_OK):
                self.resetBuyer()
                obj = dlg.getContactObj()
                self.comboBuyer.SetValue(obj.getText())
            else:
                self.comboBuyer.SetValue('')

    def OnBtnSelStateButton(self, event):
        import DlgOrderState
        
        dlg = DlgOrderState.create(self)
        if dlg.ShowModal() == wx.ID_OK:
            self.tcState.SetValue(dlg.getSelVal())

    def OnBtnDeliveryPlanButton(self, event):
        import DlgDeliveryPlanChoice
        
        dlg = DlgDeliveryPlanChoice.create(self)
        if dlg.ShowModal() == wx.ID_OK:
            self.tcDeliveryPlan.SetValue(dlg.getSelVal())

    def setDeliveryPlan(self, planId):
        self.tcDeliveryPlan.SetValue(planId)

    def OnBtnProDetailButton(self, event):
        event.Skip()

